import {AfterViewInit, Component, ElementRef, output, ViewChild} from '@angular/core';
import { HttpClient } from '@angular/common/http';
import {ChatService} from '../../core/chat/chat.service';
import {ActivatedRoute} from '@angular/router'; // 用于获取路由参数
import {environment} from '../../../environments/environment';
import { DebuggerService } from '../../core/debugger/debugger.service';
import { Breakpoint } from '../../core/debugger/debug.interface';

import 'ace-builds/src-noconflict/ext-language_tools'; // ✅ 关键扩展
import 'ace-builds/src-noconflict/theme-github';       // ✅ 主题

import 'ace-builds/src-noconflict/mode-javascript';     // ✅ 语法模式
import 'ace-builds/src-noconflict/mode-python';
import 'ace-builds/src-noconflict/mode-c_cpp';
import 'ace-builds/src-noconflict/mode-java';


import * as ace from 'ace-builds';
import {AuthService} from '../../core/services/auth.service';
import {WebSocketMessage} from '../../core/chat/WebSocketMessage';

@Component({
  selector: 'app-problem-detail',
  templateUrl: './problem-detail.component.html',
  styleUrls: ['./problem-detail.component.css'],
  standalone: false,
})
export class ProblemDetailComponent implements AfterViewInit {
  @ViewChild('problemContainer', { static: false }) problemContainer!: ElementRef;
  @ViewChild('codeContainer', { static: false }) codeContainer!: ElementRef;
  @ViewChild('codeEditorContainer', { static: false }) codeEditorContainer!: ElementRef;
  @ViewChild('codeOutputContainer', { static: false }) codeOutputContainer!: ElementRef;
  @ViewChild('codeEditor', { static: false }) codeEditorEl!: ElementRef;

  editor!: ace.Ace.Editor;

  currentUser: any;

  selectedLanguage = 'Java';
  languages = ['Java', 'JavaScript', 'Python', 'C++'];

  private isResizingVertical = false;
  private isResizingHorizontal = false;
  private initialX = 0;
  private initialY = 0;
  private initialProblemWidth = 0;
  private initialEditorHeight = 0;

  // 组件中添加变量和方法
  roomId: string = '';
  roomMessage: string = '';

  activeTab = 'cases';
  isRunning = false;
  activeCase = 1;

  // 调试相关属性
  debuggerPanelVisible = false;
  isDebugging = false;
  editorBreakpoints: Map<number, Breakpoint> = new Map();
  currentDebugLine: number | null = null;
  private lastClickTime = 0;
  private clickDebounceDelay = 300; // 300ms防抖延迟

  // 模拟数据
  tabs = [
    { id: 'cases', label: '测试用例' },
    { id: 'result', label: '测试结果' },
    { id: 'debug', label: '调试' },
    { id: 'chat', label: '聊天'}
  ];

  testCases = [
    { id: 1, input: 'n = 5' },
    { id: 2, input: 'n = 10' },
    { id: 3, input: 'n = 0' }
  ];

  output = {
    text: '等待运行...',
    success: false
  };

  // Add new properties for custom input
  customInput: string = '';
  testResults: any[] = [];
  problemId: number = 1; // This should be set from route params

  isApplyingRemoteChange = false;
  codeHash: string = '';

  // 存储每个远程用户的 marker id
  private remoteCursors = new Map<string, number>();

  activeFeature = 'problem';
  userCode = '';
  constructor(private http: HttpClient,
              private chatService: ChatService,
              private route: ActivatedRoute,
              private authService: AuthService,
              private debuggerService: DebuggerService,
  ) {
    this.authService.currentUser.subscribe(user => {
      this.currentUser = user;
    });
  }

  ngOnInit(): void {
    // Get problem ID from route params
    this.route.params.subscribe(params => {
      this.problemId = +params['id'];
    });

    // 订阅调试会话状态
    this.debuggerService.session$.subscribe(session => {
      this.isDebugging = session !== null && session.state !== 'terminated';
      if (session && session.currentLine !== undefined) {
        this.highlightCurrentLine(session.currentLine);
      } else {
        this.clearCurrentLineHighlight();
      }
    });
  }

  ngAfterViewInit(): void {
    // const socket = new WebSocket("ws://localhost:3000/code-editor");
    // socket.onopen = function() {
    //   console.log("WebSocket connection established!");
    // };

    // 初始化编辑器前确保已导入扩展
    this.editor = ace.edit(this.codeEditorEl.nativeElement, {
      mode: 'ace/mode/java',
      theme: 'ace/theme/github',
      fontSize: 14,
      useSoftTabs: true,
      showPrintMargin: false,
    });

    // 监听编辑器内容变化
    this.editor.session.on('change', () => {
      this.userCode = this.editor.getValue();
    });

    // 启用自动补全
    (this.editor as any).setOptions({
      enableBasicAutocompletion: true,
      enableLiveAutocompletion: true,
      enableSnippets: true, // 使代码片段补全可用
    });

    // 设置断点相关的事件监听
    this.setupBreakpointHandling();

    this.editor.on('change', async (delta) => {
      if (this.isApplyingRemoteChange) return;
      const cursor = this.editor.getCursorPosition();

      this.chatService.sendDelta(delta, this.codeHash, cursor);
      this.codeHash = await this.getCodeHash(this.editor.getValue());
    });

    this.chatService.getMessages().subscribe(async (data: WebSocketMessage) => {
      const { type, subtype, content, codeHash, masterId,clientId, cursor } = data;
      console.log(cursor);
      console.log(clientId);

      // 只处理 code 类型的消息
      if (type === 'code') {
        if (subtype === 'update') {

          // 保存当前光标位置
          const cursorPosition = this.editor.getCursorPosition();

          // 如果是当前用户（房主），并且远程代码哈希不同
          if (masterId === this.currentUser.username && codeHash != this.codeHash) {
            // 代码不一致，强制同步完整代码
            this.chatService.sendFullCode(this.editor.getValue());
          } else {
            // 如果是其他用户，应用增量 delta 更新
            this.isApplyingRemoteChange = true;
            this.editor.session.getDocument().applyDelta(content);
            this.isApplyingRemoteChange = false;

            if (cursor) {
              this.showRemoteCursor(clientId, cursor);
            }
          }

          // 恢复光标位置
          this.editor.moveCursorTo(cursorPosition.row, cursorPosition.column);
        } else if (subtype === 'fullCode') {
          // 当接收到完整代码时（新加入用户或者房主代码同步）
          this.isApplyingRemoteChange = true;
          this.editor.setValue(content);
          this.isApplyingRemoteChange = false;
        }
      }

      this.codeHash = await this.getCodeHash(this.editor.getValue());
    });
  }

  // 设置断点处理
  private setupBreakpointHandling() {
    console.log('Setting up breakpoint handling...');

    // 只使用一种方法：直接监听gutter的DOM事件
    setTimeout(() => {
      const gutterElement = this.editor.container.querySelector('.ace_gutter');
      if (gutterElement) {
        console.log('Found gutter element, adding click listener');
        gutterElement.addEventListener('click', (event: Event) => {
          console.log('Direct gutter click event', event);
          const target = event.target as HTMLElement;

          // 检查是否点击的是行号单元格
          if (target.classList.contains('ace_gutter-cell')) {
            // 阻止事件冒泡，避免重复触发
            event.preventDefault();
            event.stopPropagation();

            // 获取行号
            const lineElement = target.textContent;
            if (lineElement) {
              const lineNumber = parseInt(lineElement.trim());
              if (!isNaN(lineNumber)) {
                console.log('Clicked on line number:', lineNumber);
                this.toggleBreakpoint(lineNumber);
              }
            }
          }
        });
      } else {
        console.warn('Could not find gutter element');
      }
    }, 500); // 增加延迟确保编辑器完全初始化
  }

  // 切换断点
  toggleBreakpoint(line: number) {
    // 防抖处理
    const now = Date.now();
    if (now - this.lastClickTime < this.clickDebounceDelay) {
      console.log('Click ignored due to debounce');
      return;
    }
    this.lastClickTime = now;

    console.log(`Toggling breakpoint at line ${line}`);
    const existingBreakpoint = this.editorBreakpoints.get(line);

    if (existingBreakpoint) {
      console.log('Removing existing breakpoint');
      // 移除断点
      this.removeBreakpoint(line);
    } else {
      console.log('Adding new breakpoint');
      // 添加断点
      this.addBreakpoint(line);
    }
  }

  // 添加断点
  addBreakpoint(line: number, condition?: string, logMessage?: string) {
    console.log(`Adding breakpoint at line ${line}`);
    try {
      // 创建断点对象
      const breakpoint: Breakpoint = {
        id: `bp-${line}-${Date.now()}`,
        line: line,
        condition: condition,
        enabled: true,
        verified: false,
        type: logMessage ? 'logpoint' : (condition ? 'conditional' : 'line'),
        logMessage: logMessage
      };

      this.editorBreakpoints.set(line, breakpoint);

      // 在编辑器中显示断点 - 使用ACE的内置方法
      this.editor.session.setBreakpoint(line - 1, 'ace_breakpoint');

      // 手动添加断点样式到gutter
      setTimeout(() => {
        const gutterCells = this.editor.container.querySelectorAll('.ace_gutter-cell');
        if (gutterCells[line - 1]) {
          const cell = gutterCells[line - 1] as HTMLElement;
          cell.classList.add('ace_breakpoint');
          cell.style.backgroundColor = '#e74c3c';
          cell.style.color = 'white';
          cell.style.borderRadius = '50%';
          console.log(`Applied breakpoint style to line ${line}`);
        }
      }, 100);

      // 如果有调试会话，则同步到调试服务
      if (this.debuggerService.getCurrentSession()) {
        try {
          const serviceBreakpoint = this.debuggerService.setBreakpoint(line, condition, logMessage);
          breakpoint.id = serviceBreakpoint.id;
          this.editorBreakpoints.set(line, breakpoint);
        } catch (error) {
          console.warn('Failed to sync breakpoint to debug service:', error);
        }
      }

      console.log(`Breakpoint set at line ${line}`, breakpoint);
    } catch (error) {
      console.error('Cannot set breakpoint:', error);
    }
  }

  // 移除断点
  removeBreakpoint(line: number) {
    console.log(`Removing breakpoint at line ${line}`);
    const breakpoint = this.editorBreakpoints.get(line);
    if (breakpoint) {
      // 如果有调试会话，从服务中移除
      if (this.debuggerService.getCurrentSession()) {
        try {
          this.debuggerService.removeBreakpoint(breakpoint.id);
        } catch (error) {
          console.warn('Failed to remove breakpoint from debug service:', error);
        }
      }

      this.editorBreakpoints.delete(line);

      // 从编辑器中移除断点标记
      this.editor.session.clearBreakpoint(line - 1);

      // 手动移除断点样式
      setTimeout(() => {
        const gutterCells = this.editor.container.querySelectorAll('.ace_gutter-cell');
        if (gutterCells[line - 1]) {
          const cell = gutterCells[line - 1] as HTMLElement;
          cell.classList.remove('ace_breakpoint');
          cell.style.backgroundColor = '';
          cell.style.color = '';
          cell.style.borderRadius = '';
          console.log(`Removed breakpoint style from line ${line}`);
        }
      }, 100);

      console.log(`Breakpoint removed from line ${line}`);
    }
  }

  // 高亮当前执行行
  private highlightCurrentLine(line: number) {
    this.clearCurrentLineHighlight();
    this.currentDebugLine = line;

    // 添加当前行高亮
    const Range = ace.require('ace/range').Range;
    const range = new Range(line - 1, 0, line - 1, 1);
    const marker = this.editor.session.addMarker(range, 'ace_current_debug_line', 'fullLine');

    // 滚动到当前行
    this.editor.scrollToLine(line - 1, true, true, function() {});

    // 移动光标到当前行
    this.editor.gotoLine(line, 0, true);
  }

  // 清除当前行高亮
  private clearCurrentLineHighlight() {
    if (this.currentDebugLine !== null) {
      // 移除所有当前行标记
      const markers = this.editor.session.getMarkers(false);
      for (let id in markers) {
        if (markers[id].clazz === 'ace_current_debug_line') {
          this.editor.session.removeMarker(parseInt(id));
        }
      }
      this.currentDebugLine = null;
    }
  }

  // 启动调试
  async startDebug() {
    const code = this.editor.getValue();
    if (!code.trim()) {
      alert('请先输入代码');
      return;
    }

    this.isRunning = true;
    this.activeTab = 'debug';

    try {
      const success = await this.debuggerService.startDebugSession(
        code,
        this.selectedLanguage,
        this.customInput
      );

      if (success) {
        this.debuggerPanelVisible = true;
        this.output = {
          text: '调试会话已启动',
          success: true
        };
      } else {
        this.output = {
          text: '启动调试会话失败',
          success: false
        };
      }
    } catch (error) {
      console.error('Debug start error:', error);
      this.output = {
        text: '启动调试失败：' + error,
        success: false
      };
    } finally {
      this.isRunning = false;
    }
  }

  // 停止调试
  stopDebug() {
    this.debuggerService.terminate();
    this.debuggerPanelVisible = false;
    this.clearCurrentLineHighlight();
    this.output = {
      text: '调试会话已停止',
      success: true
    };
  }

  // 调试器面板关闭处理
  onDebuggerPanelClose() {
    this.debuggerPanelVisible = false;
  }

  onFeatureChange(featureId: string) {
    this.activeFeature = featureId;
    // Update the central view accordingly
  }

  showRemoteCursor(clientId: string, cursor: { row: number, column: number }) {
    // 1. 先移除原来的标签
    const existing = document.getElementById(`cursor-${clientId}`);
    if (existing) existing.remove();

    // 2. 创建 DOM 元素显示名字
    const div = document.createElement('div');
    div.id = `cursor-${clientId}`;
    div.innerText = clientId;  // 显示 clientId

    // 设置基本样式
    div.style.position = 'absolute';
    div.style.background = '#ff4081';  // 默认颜色（后面可以动态设置）
    div.style.color = 'white';
    div.style.padding = '2px 6px';
    div.style.fontSize = '10px';
    div.style.borderRadius = '4px';
    div.style.pointerEvents = 'none';

    // 3. 获取光标位置对应的坐标（像素位置）
    const coords = this.editor.renderer.textToScreenCoordinates(cursor.row, cursor.column);

    // 4. 获取编辑器容器的边界
    const editorRect = this.editor.container.getBoundingClientRect();

    // 5. 设置光标位置（在光标的右上方）
    const left = coords.pageX - editorRect.left + 10;  // 向右偏移一点
    const top = coords.pageY - editorRect.top;  // 向上偏移一点

    // 确保 div 在容器内（避免越界）
    if (left < 0 || top < 0 || left > editorRect.width || top > editorRect.height) {
      console.warn('Invalid position for clientId', clientId, 'left:', left, 'top:', top);
      return; // 位置无效时不显示
    }

    // 6. 设置 `div` 位置
    div.style.left = `${left}px`;
    div.style.top = `${top}px`;

    // 7. 将元素添加到编辑器容器中
    this.editor.container.appendChild(div);

    // 8. 自动 3 秒后删除
    setTimeout(() => {
      div.remove();
    }, 3000);
  }

  /** 开始垂直拖动（调整左右面板宽度） */
  startVerticalResize(event: MouseEvent): void {
    event.preventDefault();
    this.isResizingVertical = true;
    this.initialX = event.clientX;
    this.initialProblemWidth = this.problemContainer.nativeElement.offsetWidth;

    document.body.style.userSelect = 'none'; // ✅ 禁止选中文本

    document.addEventListener('mousemove', this.onVerticalResize);
    document.addEventListener('mouseup', this.stopResizing);
  }

  /** 处理垂直拖动 */
  onVerticalResize = (event: MouseEvent): void => {
    if (!this.isResizingVertical) return;
    const deltaX = event.clientX - this.initialX;
    const newWidth = this.initialProblemWidth + deltaX;

    // 限制最小宽度
    if (newWidth > 200 && newWidth < window.innerWidth * 0.6) {
      this.problemContainer.nativeElement.style.width = `${Math.round(newWidth)}px`;
    }
  };

  /** 开始水平拖动（调整代码编辑区和输出区高度） */
  startHorizontalResize(event: MouseEvent): void {
    event.preventDefault();
    this.isResizingHorizontal = true;
    this.initialY = event.clientY;
    this.initialEditorHeight = this.codeEditorContainer.nativeElement.offsetHeight;

    document.body.style.userSelect = 'none'; // ✅ 禁止选中文本

    document.addEventListener('mousemove', this.onHorizontalResize);
    document.addEventListener('mouseup', this.stopResizing);
  }

  /** 处理水平拖动 */
  onHorizontalResize = (event: MouseEvent): void => {
    if (!this.isResizingHorizontal) return;
    const deltaY = event.clientY - this.initialY;
    const newHeight = this.initialEditorHeight + deltaY;

    // 限制最小高度
    if (newHeight > 100 && newHeight < window.innerHeight * 0.6) {
      this.codeEditorContainer.nativeElement.style.height = `${newHeight}px`;
      this.codeOutputContainer.nativeElement.style.height = `calc(100% - ${newHeight}px)`;
    }
  };

  /** 结束拖动 */
  stopResizing = (): void => {
    this.isResizingVertical = false;
    this.isResizingHorizontal = false;

    document.body.style.userSelect = ''; // ✅ 恢复默认

    document.removeEventListener('mousemove', this.onVerticalResize);
    document.removeEventListener('mousemove', this.onHorizontalResize);
    document.removeEventListener('mouseup', this.stopResizing);
  };

  onLanguageChange(event: Event): void {
    const lang = (event.target as HTMLSelectElement).value;
    const mode = this.mapLanguageToMode(lang);
    this.editor?.getSession().setMode(`ace/mode/${mode}`);
  }

  mapLanguageToMode(language: string): string {
    switch (language) {
      case 'Java': return "java";
      case 'JavaScript': return 'javascript';
      case 'Python': return 'python';
      case 'C++': return 'c_cpp';
      default: return 'text';
    }
  }

// 方法
  switchTab(tabId: string) {
    this.activeTab = tabId;
  }

  // Run all test cases
  submit() {
    this.isRunning = true;
    this.activeTab = 'result';

    const requestData = {
      code: this.editor.getValue().replace(/\r\n/g, '\n'),
      language: this.selectedLanguage
    };

    this.http.post(environment.apiUrl + `/code/execute/${this.problemId}`, requestData)
      .subscribe(
        (response: any) => {
          this.testResults = response;
          const allPassed = response.every((result: any) => result.status === 'SUCCESS');

          this.output = {
            text: allPassed
              ? '所有测试用例通过 ✓'
              : `错误: ${response.find((r: any) => r.status !== 'SUCCESS')?.error || '未知错误'}`,
            success: allPassed
          };
        },
        (error) => {
          this.output = {
            text: '提交失败，请稍后再试。',
            success: false
          };
          console.error(error);
        }
      )
      .add(() => {
        this.isRunning = false;
      });
  }

  // Run sample test cases
  runSampleTests() {
    this.isRunning = true;
    this.activeTab = 'result';

    const requestData = {
      code: this.editor.getValue().replace(/\r\n/g, '\n'),
      language: this.selectedLanguage
    };

    this.http.post(environment.apiUrl + `/code/execute/${this.problemId}/sample`, requestData)
      .subscribe(
        (response: any) => {
          this.testResults = response;
          const allPassed = response.every((result: any) => result.status === 'SUCCESS');

          this.output = {
            text: allPassed
              ? '示例测试用例通过 ✓'
              : `错误: ${response.find((r: any) => r.status !== 'SUCCESS')?.error || '未知错误'}`,
            success: allPassed
          };
        },
        (error) => {
          this.output = {
            text: '运行失败，请稍后再试。',
            success: false
          };
          console.error(error);
        }
      )
      .add(() => {
        this.isRunning = false;
      });
  }

  // Run with custom input
  runCustomInput() {
    if (!this.customInput.trim()) {
      this.output = {
        text: '请输入测试用例',
        success: false
      };
      return;
    }

    this.isRunning = true;
    this.activeTab = 'result';
    this.testResults = []; // Clear previous test results

    const requestData = {
      code: this.editor.getValue().replace(/\r\n/g, '\n'),
      language: this.selectedLanguage,
      input: this.customInput
    };

    this.http.post(environment.apiUrl + `/code/execute/${this.problemId}/custom`, requestData)
      .subscribe(
        (response: any) => {
          this.output = {
            text: response.status === 'SUCCESS'
              ? `输出:\n${response.output}`
              : `错误: ${response.error || '未知错误'}`,
            success: response.status === 'SUCCESS'
          };
        },
        (error) => {
          this.output = {
            text: '运行失败，请稍后再试。',
            success: false
          };
          console.error(error);
        }
      )
      .add(() => {
        this.isRunning = false;
      });
  }

  createRoom() {
    if (!/^\d{6}$/.test(this.roomId)) {
      this.roomMessage = '请输入6位数字作为房间号';
      return;
    }
    this.chatService.createRoom(this.roomId, this.currentUser.username);
    this.roomMessage = '正在创建房间...';
  }

  joinRoom() {
    if (!/^\d{6}$/.test(this.roomId)) {
      this.roomMessage = '请输入6位数字作为房间号';
      return;
    }
    this.chatService.joinRoom(this.roomId, this.currentUser.username);
    this.roomMessage = '正在加入房间...';
  }

  getCodeHash(code: string): Promise<string> {
    const encoder = new TextEncoder();
    const data = encoder.encode(code);

    return crypto.subtle.digest('SHA-256', data).then(hashBuffer => {
      const hashArray = Array.from(new Uint8Array(hashBuffer));
      const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
      return hashHex;
    });
  }
}
